#pragma once
#include <iostream>
#include <string>
#include <cstring>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <functional>
#include "Protocol.hpp"
#include "Calculate.hpp"

using namespace std;
using namespace protocol_ns;
int defaultsock = -1;
int backlog = 16;
using func_t = function<Response(const Request &)>;

class TcpServer;
class TcpData
{
public:
    TcpData(TcpServer *s, int sockfd):_s(s), _sockfd(sockfd)
    {}
    ~TcpData()
    {}
    int _sockfd;
    TcpServer *_s;
};

class TcpServer
{
public:
    TcpServer(uint16_t port, func_t func) : _port(port),_func(func), _listensock(defaultsock)
    {
    }

    void InitServer()
    {
        _listensock = socket(AF_INET, SOCK_STREAM, 0);
        if (_listensock < 0)
        {
            cerr << "socket create error" << endl;
            exit(0);
        }
        cout << "socket create success" << endl;

        struct sockaddr_in local;
        memset(&local, 0, sizeof(local));
        local.sin_family = AF_INET;
        local.sin_port = htons(_port);
        local.sin_addr.s_addr = INADDR_ANY;

        int n = bind(_listensock, (struct sockaddr *)&local, sizeof(local));
        if (n < 0)
        {
            cerr << "bind create error" << endl;
            exit(1);
        }
        cout << "bind create success" << endl;

        n = listen(_listensock, backlog);
        if (n < 0)
        {
            cerr << "listen create error" << endl;
            exit(2);
        }
        cout << "listen create success" << endl;
    }

    void Server(int sockfd)
    {
        while(true)
        {
            Request req;
            
            // 接收
            char buffer[1024];
            ssize_t r = recv(sockfd, buffer, sizeof(buffer)-1, 0);// 收快递
            if(r < 0) break;
            string recv_str;
            recv_str += buffer;

            // 解码 
            string Decode_str = DeCode(recv_str);// 拆快递，取盒子
            if(Decode_str.empty()) continue;

            // 反序列化
            req.UnSerialize(Decode_str);// 从盒子取出两支笔

            // 回调 - 计算器类函数
            Response resp = _func(req);// 两支笔-》一本书

            // 序列化
            string send_str;// 盒子
            resp.Serialize(&send_str);// 一本书放入盒子

            // 编码
            string Encode_str = EnCode(send_str);// 把盒子包装成快递

            // 发送
            ssize_t s = send(sockfd, Encode_str.c_str(), Encode_str.size(), 0);// 寄快递
            if(s < 0) break;

            cout << "recv: " << req._a << " and " << req._b << endl;
        }
        close(sockfd);
    }

    static void *HandlerTask(void *args)
    {
        pthread_detach(pthread_self());
        TcpData *td = static_cast<TcpData*>(args);
        td->_s->Server(td->_sockfd);
        delete td;
        return nullptr;
    }

    void Loop()
    {
        while (true)
        {
            struct sockaddr_in peer;
            socklen_t len = sizeof(peer);
            int sockfd = accept(_listensock, (struct sockaddr *)&peer, &len);
            if (sockfd < 0)
            {
                continue;
            }
            cout << "accept create success" << endl;

            TcpData *td = new TcpData(this, sockfd);
            pthread_t tid;
            pthread_create(&tid, nullptr, HandlerTask, td);
        }
    }

    ~TcpServer()
    {
        close(_listensock);
    }

private:
    int _listensock;
    uint16_t _port;
    func_t _func;
};